package whu.study;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class XmlConfig {
    /**
     *     模拟spring容器  用于保存bean的键值对的hashMap
     */
    private Map<String, Object> beanMap = new HashMap<>();

    public XmlConfig() { }

    /**
     *     有参构造函数 初始化xml
     */
    public XmlConfig(String xmlName) throws Exception {
        loadbean(xmlName);
    }

    /**
     * 私有方法加载bean
     */
    private void loadbean(String xmlName) throws Exception {
        //第一步 读取 xml文件
        InputStream resourceAsStream = BeanDefinition.class.getClassLoader().getResourceAsStream(xmlName);
        if (resourceAsStream == null) {
            //当找不到xml抛出异常
            throw new FileNotFoundException("该XML文件无法找到：" + xmlName);
        }
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
        Document parse = documentBuilder.parse(resourceAsStream);
        resourceAsStream.close();
        NodeList beanList = parse.getElementsByTagName("bean");
        //遍历bean标签
        for (int i = 0; i < beanList.getLength(); i++) {

            Node node = beanList.item(i);

            if (node instanceof Element) {
                Element el = (Element) node;

                String beanId = el.getAttribute("id");

                String beanClass = el.getAttribute("class");

                //第二步 反射动态获取对象
                Class beanClazz = null;
                try {
                    //加载beanClass
                    beanClazz = Class.forName(beanClass);
                } catch (ClassNotFoundException e) {
                    e.getMessage();
                    return;
                }
                //创建Bean对象
                Object beanObj = beanClazz.newInstance();

                NodeList propertyList = el.getElementsByTagName("property");

                //遍历子标签property
                for (int j = 0; j < propertyList.getLength(); j++) {
                    Node item = propertyList.item(j);
                    if (item instanceof Element) {
                        Element ele = (Element) item;
                        //拿到变量名称
                        String name = ele.getAttribute("name");
                        //拿到变量值(不一定都是String类型下面要做转换)
                        String value = ele.getAttribute("value");

                        //通过反射将bean对象指定属性
                        Field declaredField = beanObj.getClass().getDeclaredField(name);
                        //将私有属性设置为可访问
                        declaredField.setAccessible(true);
                        //获取成员属性的类型名称，若非字符串类型，则需要做相应转换
                        String fieldTypeName = declaredField.getType().getName();

                        Object o = ParamType(fieldTypeName, value);
                        //为该成员属性赋值
                        declaredField.set(beanObj, o);
                        //将该字段属性设置值


                        beanMap.put(beanId, beanObj);

                    }
                }
            }

        }
    }

    /**
     *     转换运行时参数类型（做简单演示，目前只有String Integer和int可扩展）
     */
    private Object ParamType(String fieldTypeName, String value) {
        Object obj = null;
        //判断该成员属性是否为int或Integer类型
        if ("int".equals(fieldTypeName) || "java.lang.Integer".equals(fieldTypeName)) {
            //转换为int类型并为该成员属性赋值
            int intFieldValue = Integer.parseInt(value);
            obj = intFieldValue;

        }//判断该成员属性是否为String类型
        if ("java.lang.String".equals(fieldTypeName)) {
            //为该成员属性赋值
            obj = value;
        }//判断另外类型同理
        //if(){ }
        return obj;
    }

    /**
     * 获取bean
     */
    public Object getBean(String beanName) {
        Object bean = beanMap.get(beanName);
        if (bean == null) {
            throw new IllegalArgumentException("无法实例化该名称的bean，请确定名称是否正确 " + beanName);
        }

        return bean;
    }

}







